package codegenerator.generator;

import java.util.List;

import org.slf4j.Logger;

import baytony.util.StringUtil;
import baytony.util.log.Log;
import codegenerator.CodeGeneratorException;
import codegenerator.ColumnInfo;
import codegenerator.CommonHelper;
import codegenerator.FileBean;
import codegenerator.JavaFileBean;
import codegenerator.TableInfo;
import codegenerator.config.GeneratorConfigration;

public class VoGenerator extends JavaGenerator {

	private static final Logger logger = Log.getLogger();
	private static final String VO_JTMP = "vo.jtmp";
	private static final String VO_PK_JTMP = "vo_pk.jtmp";
	private static final String PRIVATE = "private";
	private static final String ANNOTATION_ID = "@Id";
	private static final String ANNOTATION_EMBEDDED_ID = "@EmbeddedId";
	private static final String ANNOTATION_GENERATED = "@GeneratedValue(strategy=GenerationType.#type#)";
	private static final String ANNOTATION_COLUMN = "@Column";	
	private static final String PUBLIC = "public";
	private static final String VOID = "void";
	private static final String SET = "set";
	private static final String GET = "get";
	private static final String RETURN = "return";
	private static final String EQUAL = "=";
	private static final String THIS = "this";
	private static final String DOT = ".";
	private static final String NAME = "name";
	private static final String DOUBLE_QUOTE = "\"";
	private static final String PK = "Pk";
	private static final String PK_NAME = "pk";
	private static final String PROJECT_NAME = "#projectName#";
	private static final String TABLE_NAME = "#tableName#";
	private static final String CLASS_NAME = "#className#";
	private static final String ATTRIBUTE_INFO = "#attributeInfo#";
	private static final String SETTER_INFO = "#setterInfo#";
	private static final String GETTER_INFO = "#getterInfo#";

	@Override
	public FileBean createInfo(TableInfo table) throws CodeGeneratorException {
		String tableName = table.getName();
		String jtmpContent = this.readJtmpInfo(tableName);
		jtmpContent = jtmpContent.replace(PROJECT_NAME, generatorHelper.getProjectName());
		jtmpContent = jtmpContent.replace(TABLE_NAME, tableName);
		jtmpContent = jtmpContent.replace(CLASS_NAME, CommonHelper.table2ClassName(tableName));
		jtmpContent = jtmpContent.replace(ATTRIBUTE_INFO, this.createAttributes(table));
		
		
		
		String pkSetterStr = "";
		String setterStr = "";
		if(table.getPrimaryKey() != null)
			pkSetterStr = this.createPrimaryKeySetter(tableName, table.getPrimaryKey());
		if(generatorHelper.getColumnsNoPk(tableName) != null)
			setterStr = this.createSetter(generatorHelper.getColumnsNoPk(tableName));
		else
			setterStr = this.createSetter(table.getColumns());
		jtmpContent = jtmpContent.replace(SETTER_INFO, pkSetterStr + setterStr);
		
		
		
		String pkGetterStr = "";
		String getterStr = "";
		if(table.getPrimaryKey() != null)
			pkGetterStr = this.createPrimaryKeyGetter(tableName, table.getPrimaryKey());
		if(generatorHelper.getColumnsNoPk(tableName) != null)
			getterStr = this.createGetter(generatorHelper.getColumnsNoPk(tableName));
		else
			getterStr = this.createGetter(table.getColumns());
		jtmpContent = jtmpContent.replace(GETTER_INFO, pkGetterStr + getterStr);
		FileBean result = new JavaFileBean();
		result.setContent(jtmpContent);
		result.setFileName(CommonHelper.table2ClassName(tableName));
		result.setPath(generatorHelper.getSrcPath() + "vo/");
		return result;
	}
	
	private String readJtmpInfo(String tableName) {
		String jtmpContent = "";
		if(tableName.contains(PK))
			jtmpContent = super.readJtmp(VO_PK_JTMP);
		else
			jtmpContent = super.readJtmp(VO_JTMP);
		return jtmpContent;
	}
	
	public String createAttributes(TableInfo table) throws CodeGeneratorException {
		StringBuffer sb = new StringBuffer();
		String tableName = table.getName();
		List<ColumnInfo> primaryKey = table.getPrimaryKey();
		logger.debug("table name : " + tableName);
		if(primaryKey!=null && primaryKey.size()!=0) {
			//複合主鍵
			if(primaryKey.size()>1) {				
				sb.append(ANNOTATION_EMBEDDED_ID);
				sb.append(GeneratorConfigration.SEPARATOR);
				String type = this.createMutiplePrimaryKey(tableName, primaryKey);
				sb.append(PRIVATE);
				sb.append(SPACE);
				sb.append(type);
				sb.append(PK);
				sb.append(SPACE);
				/*sb.append(CommonHelper.column2Attribute(type));
				sb.append(PK);*/
				sb.append(PK_NAME);
				sb.append(SEMICOLON);
				sb.append(GeneratorConfigration.SEPARATOR);
			}
			else {
				//單一主鍵
				ColumnInfo column = primaryKey.get(0);
				String type = column.getType();
				String name = column.getName();
				sb.append(ANNOTATION_ID);
				sb.append(GeneratorConfigration.SEPARATOR);				
				sb.append(this.getGenerationType());
				sb.append(PRIVATE);
				sb.append(SPACE);
				sb.append(CommonHelper.dbType2JavaType(type));
				sb.append(SPACE);
				sb.append(CommonHelper.column2Attribute(name));
				sb.append(SEMICOLON);
				sb.append(GeneratorConfigration.SEPARATOR);
			}
		}		
		
		List<ColumnInfo> columns = table.getColumns();
		if(columns!=null) {
			String type = null;
			String name = null;
			for(ColumnInfo column : columns) {
				type = column.getType();
				name = column.getName();
				sb.append(ANNOTATION_COLUMN);
				sb.append(LEFT_SMALL_BRACKET);
				sb.append(NAME);
				sb.append(EQUAL);
				sb.append(DOUBLE_QUOTE);
				sb.append(name);
				sb.append(DOUBLE_QUOTE);
				sb.append(RIGHT_SMALL_BRACKET);
				sb.append(GeneratorConfigration.SEPARATOR);
				sb.append(PRIVATE);
				sb.append(SPACE);
				sb.append(CommonHelper.dbType2JavaType(type));
				sb.append(SPACE);
				sb.append(CommonHelper.column2Attribute(name));
				sb.append(SEMICOLON);
				sb.append(GeneratorConfigration.SEPARATOR);				
			}
		}
		return sb.toString();
	}
	
	public String createPrimaryKeySetter(String tableName, List<ColumnInfo> columns) {
		StringBuffer sb = new StringBuffer();
		String type = null;		
		if(columns.size() == 1) {
			sb.append(this.createSetter(columns));
		}
		else if(columns.size() > 1) {
			type = CommonHelper.table2ClassName(tableName);
			sb.append(PUBLIC);
			sb.append(SPACE);
			sb.append(VOID);
			sb.append(SPACE);
			sb.append(SET);
			sb.append(PK);
			sb.append(LEFT_SMALL_BRACKET);
			sb.append(type);
			sb.append(PK);
			sb.append(SPACE);
			sb.append(PK_NAME);
			sb.append(RIGHT_SMALL_BRACKET);
			sb.append(LEFT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(THIS);
			sb.append(DOT);
			sb.append(PK_NAME);
			sb.append(EQUAL);
			sb.append(PK_NAME);
			sb.append(SEMICOLON);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(RIGHT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
		}
		return sb.toString();
	}
	
	public String createPrimaryKeyGetter(String tableName, List<ColumnInfo> columns) {
		StringBuffer sb = new StringBuffer();
		String type = null;
		if(columns.size() == 1) {
			sb.append(this.createGetter(columns));
		}
		else if(columns.size() > 1) {
			type = CommonHelper.table2ClassName(tableName);
			sb.append(PUBLIC);
			sb.append(SPACE);
			sb.append(type);
			sb.append(PK);
			sb.append(SPACE);
			sb.append(GET);
			sb.append(PK);
			sb.append(LEFT_SMALL_BRACKET);
			sb.append(RIGHT_SMALL_BRACKET);
			sb.append(LEFT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(RETURN);
			sb.append(SPACE);
			sb.append(THIS);
			sb.append(DOT);
			sb.append(PK_NAME);
			sb.append(SEMICOLON);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(RIGHT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
		}
		return sb.toString();
	}
	
	public String createSetter(List<ColumnInfo> columns) {
		StringBuffer sb = new StringBuffer();
		for(ColumnInfo column : columns) {
			String name = column.getName();
			String type = column.getType();
			sb.append(PUBLIC);
			sb.append(SPACE);
			sb.append(VOID);
			sb.append(SPACE);
			sb.append(SET);
			sb.append(CommonHelper.column2MethodName(name));
			sb.append(LEFT_SMALL_BRACKET);
			sb.append(CommonHelper.dbType2JavaType(type));
			sb.append(SPACE);
			sb.append(CommonHelper.column2Attribute(name));
			sb.append(RIGHT_SMALL_BRACKET);
			sb.append(LEFT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(THIS);
			sb.append(DOT);			
			sb.append(CommonHelper.column2Attribute(name));
			sb.append(EQUAL);
			sb.append(CommonHelper.column2Attribute(name));
			sb.append(SEMICOLON);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(RIGHT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
		}
		return sb.toString();
	}
	
	public String createGetter(List<ColumnInfo> columns) {
		StringBuffer sb = new StringBuffer();
		for(ColumnInfo column : columns) {
			String name = column.getName();
			String type = column.getType();
			sb.append(PUBLIC);
			sb.append(SPACE);
			sb.append(CommonHelper.dbType2JavaType(type));
			sb.append(SPACE);
			sb.append(GET);
			sb.append(CommonHelper.column2MethodName(name));
			sb.append(LEFT_SMALL_BRACKET);			
			sb.append(RIGHT_SMALL_BRACKET);
			sb.append(LEFT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(RETURN);
			sb.append(SPACE);
			sb.append(THIS);
			sb.append(DOT);
			sb.append(CommonHelper.column2Attribute(name));
			sb.append(SEMICOLON);
			sb.append(GeneratorConfigration.SEPARATOR);
			sb.append(RIGHT_LARGE_BRACKET);
			sb.append(GeneratorConfigration.SEPARATOR);
		}
		return sb.toString();
	}
	
	public String createMutiplePrimaryKey(String tableName, List<ColumnInfo> columns) throws CodeGeneratorException {
		logger.trace("*** create mutiple primary key ***");
		TableInfo table = new TableInfo();
		logger.debug("mutiple pk name : " + tableName + PK);
		table.setName(tableName + "_" + PK);
		table.setColumns(columns);
		super.generate(table);
		return CommonHelper.table2ClassName(tableName);
	}
	
	private String getGenerationType() {
		String type = generatorHelper.getGenerationType();
		if(StringUtil.isEmptyString(type)) {
			return "";
		}
		else {
			String result = ANNOTATION_GENERATED;
			result = result.replaceAll("#type#", type);
			result += GeneratorConfigration.SEPARATOR;
			return result;
		}
	}
	

}
